local MobaMapView = MClass("MobaMapView")
local Tower= require("app.battleV3.ui.objs.Tower")
local Head= require("app.battleV3.ui.objs.MeleeHead")

function MobaMapView:ctor()
    --self.root 默认为根节点
    --设置事件
    self.panel = self:findChild("Panel")
    self.size = self.panel:getContentSize()
    self.mapLine = self:findChild("Panel/line")
    self.base   = self:findChild("Panel/Panel_tower/base")
    self.buildingPosy = self.base:getPositionY()
    self.mobaMapWin = cc.CSLoader:createNode(Res.MeleeMapWin,false,true)
    self.mobaMapWinPanel = self.mobaMapWin:findChild("Panel")
    self.panel:addChild(self.mobaMapWin,999)
    self.mobaMapWin:setPositionY(self.size.height/2)
    self:init()

    self.mapWinSize = self.mobaMapWinPanel:getContentSize()
end

function MobaMapView:init()
    self.mapWidth = self.mapLine:getContentSize().width
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.MELEE_MAP,handler(self,MobaMapView.setData))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.SHOW_MELEE_MAP,handler(self,MobaMapView.show))
    BattleUIEvent:addEventListener(BattleUIEvent.TYPE.MELEE_DEADCD,handler(self,MobaMapView.setCD))

    self.buildings = {}
    self.unitHeads = {}
    local function onNodeEvent(event)
        if "enter" == event then
        elseif "exit" == event then
            for _,child in pairs(self.buildings) do
                child:removeFromParent()
            end

            for _,child in pairs(self.unitHeads) do
                if child ~= "removed" then
                    child:removeFromParent()
                end
            end

            if not cc.isDead(self.mobaMapWin) then
                self.mobaMapWin:removeFromParent()
                self.mobaMapWin = nil
            end

            if self.touchListener then
                self:getEventDispatcher():removeEventListener(self.touchListener)
                self.touchListener = nil
            end

            if self.touchLayer then
                self.touchLayer:removeFromParent()
                self.touchLayer = nil
            end
        end
    end
    self:registerScriptHandler(onNodeEvent) 
    self:setVisible(false)
    self.bVisible = false
    self.bInit = true
end

function MobaMapView:initTouch()
    local touchLayer = display.newLayer()
    local touchSize = self.panel:getContentSize()
    touchLayer:setContentSize(touchSize)
    touchLayer:setPosition(cc.p(-touchSize.width,-touchSize.height))
    touchLayer:setTouchEnabled(true)
    self.root:addChild(touchLayer)
    local function touchBegan(touch, event)
        if not self.bVisible then
            return false
        end

        local locationX,locationY = touch:getLocation2()
        local boundingBox = self.mobaMapWinPanel:getBoundingBox()
        local pos = self.mobaMapWin:convertToNodeSpace(cc.p(locationX,locationY))

        local panelboundingBox = self.panel:getBoundingBox()
        local panelPos = self.root:convertToNodeSpace(cc.p(locationX,locationY))
        if cc.rectContainsPoint(panelboundingBox,panelPos) then
            if cc.rectContainsPoint(boundingBox,pos) then
                self.canMove = true
                return true
            else
                self.canMove = false
                return true
            end
        else
            return false
        end
    end

    local function touchMoved(touch, event)
        if self.canMove then
            local locationX,locationY = touch:getLocation2()
            local boundingBox = self.mobaMapWinPanel:getBoundingBox()
            local localPos = self.panel:convertToNodeSpace(cc.p(locationX,locationY))

            local panelboundingBox = self.panel:getBoundingBox()
            local panelPos = self.root:convertToNodeSpace(cc.p(locationX,locationY))
            if cc.rectContainsPoint(panelboundingBox,panelPos) then
                if self.locationCfg then
                    self.mobaMapWin:setPositionX(localPos.x)
                    BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_FOCUS,self.locationCfg:getPosOnEntityLayerByPosOffset(self:getOffsetOfMap(locationX)))
                end
            else
                --return false
            end
            
        end
    end

    local function touchEnded(touch, event)
        local locationX,locationY = touch:getLocation2()
        local localPos = self.panel:convertToNodeSpace(cc.p(locationX,locationY))

        local panelboundingBox = self.panel:getBoundingBox()
        local panelPos = self.root:convertToNodeSpace(cc.p(locationX,locationY))
        if cc.rectContainsPoint(panelboundingBox,panelPos) then
            if self.locationCfg then
                self.mobaMapWin:setPositionX(localPos.x)
                BattleUIEvent:dispatchEvent(BattleUIEvent.TYPE.MELEE_FOCUS,self.locationCfg:getPosOnEntityLayerByPosOffset(self:getOffsetOfMap(locationX)))
            end
        end
    end

    local touchListener = cc.EventListenerTouchOneByOne:create()
    touchListener:registerScriptHandler(touchBegan,cc.Handler.EVENT_TOUCH_BEGAN)
    touchListener:registerScriptHandler(touchMoved,cc.Handler.EVENT_TOUCH_MOVED)
    touchListener:registerScriptHandler(touchEnded,cc.Handler.EVENT_TOUCH_ENDED)
    self:getEventDispatcher():addEventListenerWithSceneGraphPriority(touchListener, touchLayer)
    self.touchListener = touchListener
    self.touchLayer = touchLayer
end

function MobaMapView:getOffsetOfMap(worldPosx)
    local pos = self.mapLine:convertToNodeSpace(cc.p(worldPosx, 0))
    return pos.x/self.mapWidth
end

function MobaMapView:show()
    self.bVisible = not self.bVisible
    self:setVisible(self.bVisible)
end

function MobaMapView:hide()
    self.bVisible = false
    self:setVisible(false)
end

function MobaMapView:setData(views, locationCfg, battleType)
    if not self.bVisible or not locationCfg then
        return
    end

    self.locationCfg = locationCfg
    if self.bInit then
        self.mobaMapWinPanel:setScaleX(self.mapWidth*display.width/locationCfg:getWidthOnEntityLayer(locationCfg.logicWidth)/self.mapWinSize.width)
        self.bInit = false
    end
    for _, head in pairs(self.unitHeads) do
        if head ~= "removed" then
            head:setShouldRemove(true)
        end
    end
    local currentHead
    local x
    local wpos
    local pos
    local localPos
    for id, view in pairs(views) do
        x = self.mapWidth*locationCfg:getPosOffsetXOnMap(view:getPositionX())
        wpos = self.mapLine:convertToWorldSpace(cc.p(x, 0))
        pos = self.panel:convertToNodeSpace(wpos)

        local canAddIconToMap = view:isHero()
        if battleType == Enums.EBattleType.BtType_Zombie then
            if view:isHero() then
                canAddIconToMap = true
            else
                canAddIconToMap = not view:getHideHead()
            end
        end

        if canAddIconToMap then
            currentHead = self.unitHeads[id]
            if currentHead and currentHead ~= "removed" then
                currentHead:setPositionX(pos.x)
                currentHead:setDead(view:isDead())
                currentHead:setShouldRemove(false)
                if view == MapManager:getMap():getFocusBattleActor() then
                    localPos = self.panel:convertToNodeSpace(cc.p(wpos.x,wpos.y))
                    self.mobaMapWin:setPositionX(localPos.x)
                end
                if battleType == Enums.EBattleType.BtType_Zombie
                  and not view:isHero()
                  and view:isDead() then
                    currentHead:setShouldRemove(true)
                end
            elseif currentHead == nil then
                self.unitHeads[id] = self:getHeadByType(view:isEnemy())
                self.unitHeads[id]:setIcon(view:getCurrentIcon())
                self.unitHeads[id]:setPositionX(pos.x)
                self.unitHeads[id]:setPositionY(self.buildingPosy)
                if view:isEnemy() then
                    self.panel:addChild(self.unitHeads[id].root,2)
                else
                    self.panel:addChild(self.unitHeads[id].root,3)
                end

                if view:isSelf() then
                    self.unitHeads[id]:setLocalZOrder(998)
                    self.unitHeads[id]:setBeSelf(true)
                    self.currentPlayerHead = self.unitHeads[id]
                end
            end
        else
            local buildingType = view:getBuildingType()
            -- 规则：基地和防御塔加入小地图显示
            if buildingType == Enums.buildingType.base or buildingType == Enums.buildingType.tower then
                if not self.buildings[id] then
                    self.buildings[id] = self:getViewByType(buildingType,view:isEnemy(),view:isNeutral())
                    self.buildings[id]:setPositionX(pos.x)
                    self.buildings[id]:setPositionY(self.buildingPosy)
                    self.panel:addChild(self.buildings[id].root,1)
                    if view.hpPercent < 1 and view.hpPercent > 0 then
                        self.buildings[id]:setHpVisible(true)
                        self.buildings[id]:setHpPercent(view.hpPercent)
                    else
                        self.buildings[id]:setHpVisible(false)
                    end
                else
                    self.buildings[id]:setRuin(view:isDead())
                    if view:isDead() then
                        self.buildings[id]:setHpVisible(false)
                    else
                        if view.hpPercent < 1 and view.hpPercent > 0 then
                            self.buildings[id]:setHpVisible(true)
                            self.buildings[id]:setHpPercent(view.hpPercent)
                        else
                            self.buildings[id]:setHpVisible(false)
                        end
                    end
                end
            end
        end
    end
    local removeIds = {}
    for id, head in pairs(self.unitHeads) do
        if head ~= "removed" and head:getShouldRemove() then
            table.insert(removeIds, id)
        end
    end
    for _, id in ipairs(removeIds) do
        self.unitHeads[id]:removeFromParent()
        self.unitHeads[id] = "removed"
    end
end

function MobaMapView:setCD(time,needTime,uid)
    if self.currentPlayerHead then
        self.currentPlayerHead:setCD(time,needTime)
    end
end

function MobaMapView:getViewByType(buildingType,bEnemy,bNeutral)
    local towerObj= Tower.new(cc.CSLoader:createNode(Res.MeleeTower,false,true))
    towerObj:setBuildingType(buildingType,bEnemy,bNeutral)
    return towerObj
end

function MobaMapView:getHeadByType(bEnemy)
    local headObj= Head.new(cc.CSLoader:createNode(Res.MeleeHead,false,true))
    headObj:setEnemy(bEnemy)
    return headObj
end

return MobaMapView